<?php

namespace app\common\service;

use app\common\service\Base;
use think\Db;
class Stock extends Base
{
	/**
	 * 获取库存量
	 *
	 * @author KING
	 * @date 2020年6月2日
	 *
	 * @param integer $materialId
	 * @return number
	 */
	public function getStockLeft($materialId,$factoryid=0) {
		if (empty($materialId)) return 0;
		return round(db('stock')->where([['material_id','eq',$materialId],['factory_id','eq',$factoryid]])->order("stock desc")->sum('stock'), 2);
	}

    /**
     * 批量申请入库/出库操作,产生待入库的数据
     * $changeStockList 数据格式[[list1],[list2],..]
     * @param stock_m_type 验布缩水   常规料入库，备料入库， 余料入库(含退料入库），
     */
	public function applyCheckIn($changeStockList,$actionRemark='',$writelog=true){
	    //'stock'=>,'material_id'=>,'in_factory'=>,'stock_m_type'=>'','client_ordernum','order_id','out_stockid'=>,'action_state','cloth_num',stock_action_id,check_out_type],
        //提供的数据格式出库id,入库库存，物料id,入库工厂，物料属性，采购批号/订单号,订单orderid,执行状态，布号,申请记录id,出库类型(批量/面料)
        db()->startTrans();
        $batch_number='';//批量操作编号
        $outintype=1;//操作日志出入库方式 1入库0出库
        $checkout_state_txt=[100=>'提交出库待发货',101=>'出库已发货'];
        foreach ($changeStockList as $key=>$changeInfo){
            $changeInfo['out_stockid'] = $changeInfo['out_stockid'] ?? 0;
            $stockinfo=db('stock')->find($changeInfo['out_stockid']);
            if(!empty($changeInfo['out_stockid'])){ //存在出库的数据id, 是调拨出库过来的入库
                //更新出库方的库存到占用量里面
                db('stock')->where('id',$changeInfo['out_stockid'])->update(['stock'=>$stockinfo['stock']-$changeInfo['stock'],'apply_used'=>$stockinfo['apply_used']+$changeInfo['stock']]);
                $outintype=0;
            }
            $batch_number=arrayGet($changeInfo, 'batch_number', $batch_number);//批量操作编号
            $storehouse_id=empty($changeInfo['storehouse_id']) ? 0 : $changeInfo['storehouse_id'];
            $storeshelf_id=empty($changeInfo['storeshelf_id']) ? 0 : $changeInfo['storeshelf_id'];
            $changeInfo['client_ordernum']=isset($changeInfo['client_ordernum']) ? $changeInfo['client_ordernum'] : '';
            $changeInfo['caigou_number']=isset($changeInfo['caigou_number']) ? $changeInfo['caigou_number'] : '';
            //生成待入库记录
            $insData = [
                'stock_m_type'=>$changeInfo['stock_m_type'],
                'check_out_type'=>arrayGet($changeInfo, 'check_out_type', 1),
                'type' =>arrayGet($changeInfo, 'check_type', 1), //进出方式（1入，2出）
                'stock_id'=>$changeInfo['out_stockid'],
                'batch_number'=>$batch_number,
                'cloth_num'=> isset($changeInfo['cloth_num']) ? $changeInfo['cloth_num'] : '',
                'use_num' =>$changeInfo['stock'],
                'material_id' => $changeInfo['material_id'],
                'factory_id' => $changeInfo['in_factory'],
                'order_id' => isset($changeInfo['order_id']) ? $changeInfo['order_id'] : 0, //常规料订单id
                'client_ordernum'=>isset($changeInfo['client_ordernum']) ? $changeInfo['client_ordernum'] : '', //客户订单号
                'caigou_number'=>$changeInfo['caigou_number'],
                'sku'=>isset($changeInfo['sku']) ? $changeInfo['sku'] : '',
                'remark'=>isset($changeInfo['remark']) ? $changeInfo['remark'] : '',
                'storehouse_id'=>$storehouse_id,
                'storeshelf_id'=>$storeshelf_id,
                'action_state'=>isset($changeInfo['action_state']) ? $changeInfo['action_state'] : 100,    //出入库执行状态  100待入库/提交出库待入库，101出库已发货待入库 110已入库
                'adminid_checkout' => ADMIN_ID,
                'adminid_create'=>ADMIN_ID,
                'create_time' => time(),
                'update_time' => time(),
            ];
            $stock_m_type = config('mimo.stock_m_type');//0常规1备料2余料
            $actionid = $changeStockList[$key]['actionid'] = db('stock_action')->insertGetId($insData);
            //更新批量操作编号
            if($batch_number==''){
                $batch_number=$actionid;
                db('stock_action')->where('id', $actionid)->update(['batch_number'=>$actionid]);
            }
            $action_factory=!empty($changeInfo['out_stockid']) ? $stockinfo['factory_id'] : $changeInfo['in_factory']; //操作工厂
            // 记录出入库操作日志
            //stock_id,material_id,stock操作库存量,type操作类型3盘点2退回1进0出,feed_id执行表stock_action_id
            $logdata=['stock_id'=>$changeInfo['out_stockid'],'material_id'=>$changeInfo['material_id'],'stock'=>$changeInfo['stock'],'factory_id' => $action_factory,'client_ordernum' => $changeInfo['client_ordernum'],
                'caigou_number'=>$changeInfo['caigou_number'],
                'type'=>$outintype,'feed_id'=>$actionid
            ];
            $logtxt='申请入库';
            $logtxt= !empty($changeInfo['out_stockid']) ? $checkout_state_txt[$insData['action_state']] :$logtxt;
            $logtxt=$actionRemark!='' ? $actionRemark : $logtxt;
            if($writelog){
                $this->addStockLog($logdata,$logtxt);
            }
        }
        db()->commit();
        return $changeStockList;
    }

    /**
     * 撤消入库申请 撤消出库申请
     */
    public function applyCheckInCallBack($backData,$actionRemark='撤消占用出库'){
        //$backData=[[applyid, stock_id, material_id, client_ordernum, stock_m_type, batch_number, ],,]  client_ordernum+9//
        db()->startTrans();
        foreach ($backData as $key=>$backinfo) {
            if(!empty($backinfo['applyid'])){
                $applyinfo=db('stock_action')->find($backinfo['apply_id']);
            }else{ //占用出库撤销
                $applyinfo=db('stock_action')->where([['batch_number', '=', $backinfo['client_ordernum']."9"],['material_id', '=', $backinfo['material_id']],['stock_id', '=', $backinfo['stock_id']]])->find();
            }
            $logdata=['stock_id'=>$applyinfo['stock_id'],'material_id'=>$backinfo['material_id'],'stock'=>$applyinfo['use_num'],'factory_id' => $applyinfo['factory_id'],'client_ordernum' => $backinfo['client_ordernum'],
                'caigou_number'=>$applyinfo['caigou_number'],'type'=>1
            ];
            $stockinfo=db('stock')->where('id',$applyinfo['stock_id'])->find();
            $apply_used=$stockinfo['apply_used']-$applyinfo['use_num']<0 ? 0 : $stockinfo['apply_used']-$applyinfo['use_num'];
            db('stock')->where('id',$applyinfo['stock_id'])->update(['stock'=>$stockinfo['stock']+$applyinfo['use_num'],'apply_used'=>$apply_used]);
            $this->addStockLog($logdata,$actionRemark);
            $applyinfo=db('stock_action')->where('id', $applyinfo['id'])->delete();
        }
        db()->commit();
        return true;
    }

    //执行出库
    public function doCheckout($checkinDatas,$actionRemark='采购占用出库'){
        //'apply_id'=>,'stock'=>,'material_id'=>,'in_factory'=>,'storehouse_id','storeshelf_id'],
        db()->startTrans();
        $cloth_num_str='';//布号
        $batch_number=0;//批量操作编号
        foreach ($checkinDatas as $key=>$checkin){
            $applyinfo=db('stock_action')->find($checkin['apply_id']);
            if($applyinfo['action_state']==110){
                $this->error('出库申请列表存在已经执行过出库的记录，请误重复入库');
            }
            if(!empty($applyinfo['stock_id'])){ //存在出库的数据id, 是调拨出库过来的入库
                //将出库方的 总占用量减掉本次入库
                db('stock')->where('id',$applyinfo['stock_id'])->setDec('apply_used',$checkin['stock']);
                $stockinfo=db('stock')->find($applyinfo['stock_id']);
                $applyinfo['caigou_number']=$stockinfo['caigou_number'];
                $cloth_num_str.=$stockinfo['cloth_num'].",";
            }
            //为物料进度里的物料 记录出库记录
            $ominfo=db('order_material')->where([['material_id','eq',$applyinfo['material_id']],['client_ordernum','eq',$applyinfo['client_ordernum']]])->find();
            if(!empty($ominfo) && $key+1>=count($checkinDatas)){ //多条占用出库只写一条日志
                $ominfo['name']="订单/备:".$applyinfo['caigou_number'].'物料'.
                $ominfo['type']='';$ominfo['tiaoshu']=count($checkinDatas);$ominfo['cloth_num']=trim($cloth_num_str,',');
                $this->addOrderMaterialLog($ominfo['mid'],$ominfo);
                //更新占用出库状态
                $stockstate=db('order_material')->where([['material_id','eq',$applyinfo['material_id']],['client_ordernum','eq',$applyinfo['client_ordernum']]])->update(["stock_checkout_state"=>1]);
            }
            // 新物料记录入库操作日志
            //stock_id,material_id,stock操作库存量,type操作类型3盘点2退回1进0出,feed_id执行表stock_action_id
            $logdata=['stock_id'=>$applyinfo['stock_id'],'material_id'=>$applyinfo['material_id'],'stock'=>$checkin['stock'],'factory_id' => $checkin['in_factory'],'client_ordernum' => $applyinfo['client_ordernum'],
                'caigou_number'=>$applyinfo['caigou_number'],
                'type'=>2,'feed_id'=>$applyinfo['stock_id']];
            $this->addStockLog($logdata,$actionRemark);
            db('stock_action')->where('id',$checkin['apply_id'])->update(['action_state'=>110,'factory_id' => $checkin['in_factory'],
                'adminid_checkout'=>ADMIN_ID,'update_time' => time(),'caigou_number'=>$applyinfo['caigou_number']]);
        }
        db()->commit();
        return true;
    }

    //为物料进度里的物料 增加记录操作日志
    public function addOrderMaterialLog($mid,$omInfo){
        // 记录操作日志
        $logData = [
            'order_material_id' => $mid,
            'factory_id' => $omInfo['factory_id'],
            'material_id' => arrayGet($omInfo, 'material_id', 0),
            'material_name' => arrayGet($omInfo, 'name', ''),
            'material_type' => arrayGet($omInfo, 'type', ''),
            'cloth_num'=>arrayGet($omInfo, 'cloth_num', ''),
            'type' => 4, //占用库存出库
            'order_id' => $omInfo['order_id'],
            'client_ordernum' => $omInfo['client_ordernum'],
            'color' => arrayGet($omInfo, 'color', ''),
            'tiaoshu' => $omInfo['tiaoshu'],
            'remark' => '占用库存出库' ,
            'stalls_id' => 0,
            'is_from_stock' => 0,
            'is_renew' => 0,
            'admin_id' => ADMIN_ID,
            'create_time' => time(),
            'update_time' => time(),
        ];
        db('order_material_log')->insertGetId($logData);
    }

    /**
     *对 待入库的数据 执行入库操作，将待入库申请变成已入库，入库方增加库存，出库方扣除占用数量；
     */
    public function doCheckIn($checkinDatas){
        //'apply_id'=>,'stock'=>,'material_id'=>,'in_factory'=>,'storehouse_id','storeshelf_id'],
        db()->startTrans();
        $batch_number=0;//批量操作编号
        foreach ($checkinDatas as $key=>$checkin){
            $applyinfo=db('stock_action')->find($checkin['apply_id']);
            if($applyinfo['action_state']==110){
                $this->error('入库申请列表存在已经执行过入库的记录，请误重复入库');
            }
            if(!empty($applyinfo['stock_id'])){ //存在出库的数据id, 是调拨出库过来的入库
                //将出库方的 总占用量减掉本次入库
                $stockinfo=db('stock')->where('id',$applyinfo['stock_id'])->find();
                db('stock')->where('id',$applyinfo['stock_id'])
                    ->update(["apply_used"=>$stockinfo['apply_used']+$applyinfo['use_num']-$checkin['stock'],'stock'=>$stockinfo['stock']+$applyinfo['use_num']-$checkin['stock']]);

            }
            $checkin['client_ordernum']=empty($checkin['client_ordernum']) ? $applyinfo['client_ordernum'] : $checkin['client_ordernum'];
            $storehouse_id=empty($checkin['storehouse_id']) ? 0 : $checkin['storehouse_id'];
            $storeshelf_id=empty($checkin['storeshelf_id']) ? 0 : $checkin['storeshelf_id'];
            //id, material_id, factory_id, stock,  apply_used, storehouse_id, storeshelf_id, unit, create_time,update_time
            //执行入库操作
            $insData = [
                'stock_m_type'=>$applyinfo['stock_m_type'],
                'apply_used'=>0,
                'out_stock_id'=>$applyinfo['stock_id'],
                'cloth_num'=>$applyinfo['cloth_num'],
                'stock' =>$checkin['stock'],
                'material_id' => $applyinfo['material_id'],
                'factory_id' => $checkin['in_factory'],
                'storehouse_id'=>$storehouse_id,
                'storeshelf_id'=>$storeshelf_id,
                'client_ordernum'=>$checkin['client_ordernum'], //客户订单号
                'caigou_number'=>$applyinfo['caigou_number'],
                'create_time' => time(),
                'update_time' => time(),
            ];
            $stock_m_type = config('mimo.stock_m_type');//0常规1备料2余料
            $newStockid = db('stock')->insertGetId($insData);
            //如果是余料入库，将旧余料信息关连上这个库存id
            $remarkinfo=explode(":",$applyinfo['remark']);
            //$material_stockid=$applyinfo['stock_m_type']==2 ? end($remarkinfo) : 0;
            //db('material_stock')->where('id', $material_stockid)->update(['stock_id'=>$newStockid]);
            //增加该物料来源操作日志

            // 新物料记录入库操作日志
            //stock_id,material_id,stock操作库存量,type操作类型3盘点2退回1进0出,feed_id执行表stock_action_id
            $logdata=['stock_id'=>$newStockid,'material_id'=>$applyinfo['material_id'],'stock'=>$checkin['stock'],'factory_id' => $checkin['in_factory'],'client_ordernum' => $applyinfo['client_ordernum'],
                'caigou_number'=>$applyinfo['caigou_number'],
                'type'=>1,'feed_id'=>$applyinfo['stock_id']];
            $logtxt='执行入库';//$stock_m_type[$applyinfo['stock_m_type']]
            $this->addStockLog($logdata,$logtxt);
            //出库物料记录日志
            $logdata['type']=0;
            $logdata['stock']=0;
            $logdata['stock_id']=$applyinfo['stock_id'];
            $logdata['feed_id']=0;
            $logtxt='入库方已执行入库';
            //$this->addStockLog($logdata,$logtxt);
            //更新待入库记录为已入库状态
            db('stock_action')->where('id',$checkin['apply_id'])->update(['action_state'=>110,'factory_id' => $checkin['in_factory'],'use_num'=>$checkin['stock'],
                'client_ordernum'=>$checkin['client_ordernum'],'adminid_checkin'=>ADMIN_ID]);
        }
        db()->commit();
        return true;
    }

    /**
     *已入库的数据，返回重置与doCheckIn方法相对
     */
    public function doCheckInCallBack($checkinDatas)
    {
        //'apply_id'=>],
        Db::startTrans();
        foreach ($checkinDatas as $key => $checkin) {
            $applyinfo = db('stock_action')->find($checkin['apply_id']);
            if ($applyinfo['action_state'] != 110) {
                Db::rollback();
                return ['code' => 0, 'msg' => '没有此记录',];
            }
            $stock_info = db('stock')->where([
                'material_id' => $applyinfo['material_id'],
                'factory_id' => $applyinfo['factory_id'],
                'stock_m_type' => $applyinfo['stock_m_type'],
                'stock' => $applyinfo['use_num'],
                'apply_used' => 0,//没占用
            ])->find();
            if (!isset($stock_info['id'])) {
                Db::rollback();
                return ['code' => 0, 'msg' => "已占用，不能重置", 'data' => $stock_info,];
            }
            //stock stock_action表修改或删除
            db('stock')->where(['id' => $stock_info['id']])->delete();
            db('stock_action')->where(['id' => $applyinfo['id']])->update([
                'action_state' => 100,
                'update_time' => time(),
            ]);
            //记录日志
            $logdata['type'] = 2;
            $logdata['stock'] = $applyinfo['use_num'];
            $logdata['stock_id'] = $applyinfo['stock_id'];
            $logdata['feed_id'] = 0;
            $logdata['material_id'] = $applyinfo['material_id'];
            $logdata['factory_id'] = $applyinfo['factory_id'];
            $logtxt = '返回重置';
            $this->addStockLog($logdata, $logtxt, [
                'order_id' => $applyinfo['order_id'],
                'client_ordernum' => $applyinfo['client_ordernum'],
                'sku' => $applyinfo['sku'],
            ]);
        }
        Db::commit();
        return ['code' => 1, 'msg' => '成功', 'data' => [],];
    }

    /**
     * 记录材料的出库/入库日志
     * @access public
     * @param  array $data  日志数据[stock_id材料库存id,material_id材料id,stock操作库存量,type操作类型3盘点2退回1进0出,feed_id执行表stock_action_id]
     * @param  string  $sequence 自增序列名
     * @return integer|string
     */
    public function addStockLog($data,$remark='新物料入库',$orderInfo=[]){
        if(!isset($data['type']) || empty($data['material_id'])|| !isset($data['stock']) ){
            die("日志数据缺少必要参数type，material_id，stock");
        }
        $stockLog = [
            'type' => $data['type'],
            'stock_id' => $data['stock_id'],
            'material_id' => $data['material_id'],
            'operate_num' => $data['stock'],
            'left_num' => arrayGet($data, 'old_stock', 0),
            //'unit_price' => $unitPrice ? : 0,
            //'amount' => $amount ? : 0,
            'feed_id' => $data['feed_id'] ?? 0,
            'factory_id' => $data['factory_id'],// arrayGet($orderInfo, 'factory_id', 0),
            'order_id' => arrayGet($orderInfo, 'id', 0),
            'client_ordernum' => arrayGet($data, 'client_ordernum', 0),
            'caigou_number'=>arrayGet($data, 'caigou_number', ''),
            'create_adminid'=>ADMIN_ID,
            'sku' => arrayGet($orderInfo, 'sku', 0),
            'remark' => $remark,
            'create_time' => time(),
            'update_time' => time(),
        ];
        $logid=db('stock_log')->insertGetId($stockLog);
        return $logid;
    }

}